今天要來製作購物清單,透過這個練習我們可以複習 Lifting State Up 的觀念。先來看目前的程式碼:
import React from "react";
import AddNewItemForm from "./AddNewItemForm";
function App() {
return (
<div className="wrapper">
<div className="list-wrapper">
<ol className="shopping-list">
<li>Avocados</li>
<li>Broccoli</li>
<li>Carrots</li>
</ol>
</div>
<AddNewItemForm />
</div>
);
}
export default App;
import React from "react";
function AddNewItemForm() {
return (
<div className="new-list-item-form">
<form>
<label htmlFor="new-list-form-input">New item:</label>
<div className="row">
<input id="new-list-form-input" type="text" />
<button>Add</button>
</div>
</form>
</div>
);
}
export default AddNewItemForm;
畫面目前是這樣:
在 App.js 檔案中設定狀態變數,先將初始值設定為一個 empty array。
const [items, setItems] = React.useState([]);
先以假想的資料來做測試,將裡頭放置資料物件:
const [items, setItems] = React.useState([
{ label: "kiwi", id: 123 },
{ label: "banana", id: 456 },
{ label: "mango", id: 789 },
]);
{
items.map(({ id, label }) => <li key={id}>{label}</li>);
}
透過解構賦值的方法,可以在<li>
元素當中直接使用{id}
和{label}
。
現在我們可以在畫面中看到測試的資料了,這樣已經確定動態生成的功能正常運作。
接著要來編寫讓清單能夠追加項目的 function,我們在 App 元件當中創建並將這個 function 命名為handleAddItem
function handleAddItem(label) {
const newItem = {
label,
id: Math.random(),
};
const nextItems = [...items, newItem];
setItems(nextItems);
}
在這個 function 當中要處理的事情以三件,(1) 先將新 item 的組織宣告為newItem
變數,透過 id:Math.random()
來隨機產生 id,用於 JSX 所需的 key (2) 接著將 nextItems,也就是下一次渲染的清單也宣告為變數,透過展開當前的 items 並加上 newItem 來完成下一次渲染的邏輯。(3)使用-setItems()
觸發渲染。
為了讓 handleAddItem function 可以在 AddNewItemForm 當中可以使用,必須透過 props 傳遞。
<AddNewItemForm handleAddItem={handleAddItem} />
也需要在子元件 AddNewItemForm 當中來設定 props 的傳入。
function AddNewItemForm({handleAddItem})
來到 AddNewItemForm.js 的檔案中繼續編輯。先在 form 元素上添加onSubmit
attribute 並設置預防事件預設表現的 function。同時也呼叫handleAddItem
function。。
<form
onSubmit={(event) => {
event.preventDefault();
handleAddItem()
}}
>
在元件內設置狀態變數以利後續的追加項目,並在 JSX 當中綁定資料。
const [label, setlabel] = React.useState("");
<input
id="new-list-form-input"
type="text"
value={label}
onChange={(event) => {
setLabel(event.target.value);
}}
/>
添加value
和 onChange
,做法就跟我們這二天複習的操作的一樣。
這樣我們的 shopping list 大致就完成了
當我在輸入欄位輸入「cup ramen」,項目即順利被添加上去了。
這邊的小問題是,當我們輸入完輸入匡的內容並沒有被清空,所以當按下下一個 enter 鍵,資料就會重複被送出,像這樣:
這個問題可以透過追加 setLabel 來解決:
<form
onSubmit={(event) => {
event.preventDefault();
handleAddItem(label);
setLabel('')
}}
>
這樣即可追加完又將輸入匡渲染為空的 string。
將一開始放置測試資料還原為空的 array
const [items, setItems] = React.useState([]);
這樣即完成了。